package cn.xenosp.server.module.certificate.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.xenosp.server.common.error.HttpsApplyException;
import cn.xenosp.server.common.sslApply.CertbotManager;
import cn.xenosp.server.common.sslApply.CertificateInfo;
import cn.xenosp.server.common.tools.IdUtil;
import cn.xenosp.server.common.tools.ObjectConvert;
import cn.xenosp.server.common.tools.SpringBeanUtil;
import cn.xenosp.server.module.certificate.entity.SslCertificate;
import cn.xenosp.server.module.certificate.entity.SslCertificateVO;
import cn.xenosp.server.module.certificate.mapper.SslCertificateMapper;
import cn.xenosp.server.module.certificate.service.SslCertificateService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
* @author TongHui
* @description 针对表【bus_ssl_certificate(ssl证书管理)】的数据库操作Service实现
* @createDate 2025-03-06 09:51:08
*/
@Slf4j
@Service
public class SslCertificateServiceImpl extends ServiceImpl<SslCertificateMapper, SslCertificate>
    implements SslCertificateService{

    private static Set<String> applyCertificate = new HashSet<>();
    private static Set<String> renewCertificate = new HashSet<>();

    /**
     * 获取SSL证书分页数据
     *
     * 根据查询条件获取SSL证书的分页列表数据，包含分页参数和查询条件过滤。
     * 该方法是父类分页方法的特定实现，用于处理SSL证书的定制化分页查询需求。
     *
     * @param sslCertificateVO 分页查询参数对象，包含以下字段：
     *        - page: 当前页码
     *        - limit: 每页显示条数
     *        - 其他SSL证书查询条件字段
     * @return IPage 分页结果对象，包含：
     *         - records: 当前页数据列表
     *         - total: 总记录数
     *         - size: 每页显示条数
     *         - current: 当前页码
     */
    @Override
    public IPage getPage(SslCertificateVO sslCertificateVO) {
        SslCertificate sslCertificate = new SslCertificate();
        Page page = new Page(sslCertificateVO.getPage(), sslCertificateVO.getLimit());
        ObjectConvert.copyVoToEntity(sslCertificateVO,sslCertificate);
        return baseMapper.page(page,sslCertificate);
    }

    @Override
    public void add(SslCertificateVO sslCertificateVO) {
        SslCertificate one = getOne(new LambdaQueryWrapper<SslCertificate>().eq(SslCertificate::getDomain, sslCertificateVO.getDomain()));
        if (ObjectUtil.isNotEmpty(one)){
            throw new HttpsApplyException("域名重复");
        }
        try {
            CertificateInfo certificateExpiryDate = CertbotManager.getInstance().getCertificateExpiryDate(sslCertificateVO.getDomain());
            if (ObjectUtil.isNotEmpty(certificateExpiryDate)){
                sslCertificateVO.setIssuedAt(certificateExpiryDate.getNotBefore());
                sslCertificateVO.setExpiresAt(certificateExpiryDate.getNotAfter());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        SslCertificate sslCertificate = new SslCertificate();
        ObjectConvert.copyVoToEntity(sslCertificateVO,sslCertificate);
        sslCertificate.setId(IdUtil.getId());
        save(sslCertificate);
    }

    @Override
    public void save(SslCertificateVO sslCertificateVO) {
        SslCertificate sslCertificate = new SslCertificate();
        ObjectConvert.copyVoToEntity(sslCertificateVO,sslCertificate);
        updateById(sslCertificate);
    }

    @Override
    public void delete(String id) {
        removeById(id);
    }

    @Override
    public void delete(String[] ids) {
        removeByIds(Arrays.asList(ids));
    }


    @Override
    public void applyCertificate(List<SslCertificateVO> certificateList) {
        new Thread(() -> {
            for (SslCertificateVO sslCertificateVO : certificateList) {
                if (applyCertificate.contains(sslCertificateVO.getDomain())){
                    continue;
                }
                applyCertificate.add(sslCertificateVO.getDomain());
                log.info("申请证书：{}",sslCertificateVO.getDomain());
                try {
                    CertbotManager certbotManager = CertbotManager.getInstance();
                    if (certbotManager.requestCertificate(sslCertificateVO.getDomain())) {
                        CertificateInfo certificateExpiryDate = certbotManager.getCertificateExpiryDate(sslCertificateVO.getDomain());
                        SslCertificate certificate = getById(sslCertificateVO.getId());
                        if (ObjectUtil.isNotEmpty(certificate)){
                            certificate.setIssuedAt(certificateExpiryDate.getNotBefore());
                            certificate.setExpiresAt(certificateExpiryDate.getNotAfter());
                        }
                        updateById(certificate);
                    }else {
                        log.info("申请证书失败：{}",sslCertificateVO.getDomain());
                    }
                    log.info("申请证书成功：{}",sslCertificateVO.getDomain());
                } catch (Exception e) {
                    e.printStackTrace();
                    log.info("申请证书失败：{}",sslCertificateVO.getDomain());
                }
                applyCertificate.remove(sslCertificateVO.getDomain());
            }
        }).start();
    }

    @Override
    public void renewCertificate(List<SslCertificateVO> certificateList) {
        new Thread(() -> {
            for (SslCertificateVO sslCertificateVO : certificateList) {
                if (renewCertificate.contains(sslCertificateVO.getDomain())){
                    continue;
                }
                renewCertificate.add(sslCertificateVO.getDomain());
                log.info("续签证书：{}",sslCertificateVO.getDomain());
                try {
                    CertbotManager certbotManager = CertbotManager.getInstance();
                    if (certbotManager.renewCertificate(sslCertificateVO.getDomain())) {
                        CertificateInfo certificateExpiryDate = certbotManager.getCertificateExpiryDate(sslCertificateVO.getDomain());
                        SslCertificate certificate = getById(sslCertificateVO.getId());
                        if (ObjectUtil.isNotEmpty(certificate)){
                            certificate.setIssuedAt(certificateExpiryDate.getNotBefore());
                            certificate.setExpiresAt(certificateExpiryDate.getNotAfter());
                        }
                        certificate.setUpdateNumber(certificate.getUpdateNumber()+1);
                        updateById(certificate);
                    }else {
                        log.info("续签证书失败：{}",sslCertificateVO.getDomain());
                    }
                    log.info("续签证书成功：{}",sslCertificateVO.getDomain());
                } catch (Exception e) {
                    e.printStackTrace();
                    log.info("续签证书失败：{}",sslCertificateVO.getDomain());
                }
                renewCertificate.remove(sslCertificateVO.getDomain());
            }
        }).start();
    }
}




